using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;



namespace Win32SDK
{
    public sealed class Shell32
    {
        public const string Dll = "Shell32.Dll";
        private Shell32()
        {
        }

        [DllImport(Shell32.Dll, CharSet = CharSet.Auto)]
        public static extern int Shell_NotifyIcon(int message, NOTIFYICONDATA pnid);
        [DllImport(Shell32.Dll, CharSet = CharSet.Auto)]
        public static extern IntPtr ShellExecute(HandleRef hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd);
        [DllImport(Shell32.Dll, EntryPoint = "ShellExecute", CharSet = CharSet.Auto)]
        public static extern IntPtr ShellExecute_NoBFM(HandleRef hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd);
        [DllImport(Shell32.Dll, CharSet = CharSet.Ansi, ExactSpelling = true)]
        public static extern void DragAcceptFiles(HandleRef hWnd, bool fAccept);
        [DllImport(Shell32.Dll, CharSet = CharSet.Auto)]
        public static extern int DragQueryFile(HandleRef hDrop, int iFile, StringBuilder lpszFile, int cch);

        [DllImport(Shell32.Dll, CharSet = CharSet.Auto)]
        public static extern IntPtr SHGetFileInfo(
          string pszPath,
          int dwFileAttributes,
          out    SHFILEINFO psfi,
          uint cbfileInfo,
          SHGFI uFlags);


        [DllImport(Shell32.Dll)]
        public static extern int SHGetDesktopFolder(ref IShellFolder ppshf);

        [DllImport(Shell32.Dll, SetLastError = true, EntryPoint = "#2", CharSet = CharSet.Auto)]
        public static extern UInt32 SHChangeNotifyRegister(
                    IntPtr hWnd,
                    SHCNF fSources,
                    SHCNE fEvents,
                    uint wMsg,
                    int cEntries,
                    ref SHChangeNotifyEntry pFsne);
        [DllImport(Shell32.Dll, SetLastError = true, EntryPoint = "#4", CharSet = CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern Boolean SHChangeNotifyUnregister(UInt32 hNotify);
        /// <summary>
        /// Converts an item identifier list to a file system path. (Note: SHGetPathFromIDList calls the ANSI version, must call SHGetPathFromIDListW for .NET)
        /// </summary>
        /// <param name="pidl">Address of an item identifier list that specifies a file or directory location relative to the root of the namespace (the desktop).</param>
        /// <param name="pszPath">Address of a buffer to receive the file system path. This buffer must be at least MAX_PATH characters in size.</param>
        /// <returns>Returns TRUE if successful, or FALSE otherwise. </returns>
        [DllImport("shell32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool SHGetPathFromIDListW(IntPtr pidl, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder pszPath);
        
//Function SHChangeNotifyDeregister(hNotify:integer):integer;stdcall;
//         external 'Shell32.dll' index 4;
//Function SHChangeNotifyRegister(hWnd,uFlags,dwEventID,uMSG,cItems:LongWord;
//         lpps:PIDLSTRUCT):integer;stdcall;external 'Shell32.dll' index 2;
//Function SHGetFileInfoPidl(pidl : PItemIDList;
//         dwFileAttributes : Integer;
//         psfib : PSHFILEINFOBYTE;
//         cbFileInfo : Integer;
//         uFlags : Integer):Integer;stdcall;
//         external 'Shell32.dll' name 'SHGetFileInfoA';


        public static IShellFolder DesktopFolder
        {
            get
            {
                IShellFolder ret = null;
                SHGetDesktopFolder(ref ret);
                return ret;
                
            }
        }
        public static IShellFolder GetShellFolder(string path, out IntPtr pidl)
        {
            uint i, j = 0;
            IShellFolder folder;
            IntPtr p;
            uint hr;
            IShellFolder desktop = DesktopFolder;

            hr = desktop.ParseDisplayName(User32.GetDesktopWindow(), IntPtr.Zero, path, out i, out pidl, ref j);
            hr = desktop.BindToObject(pidl, IntPtr.Zero, ref Guids.IID_IShellFolder, out p);
            folder = Marshal.GetObjectForIUnknown(p) as IShellFolder;
            return folder;
        }

        public static int GetFileImageIndex(string path, bool large, bool open, bool selected)
        {
            SHFILEINFO fileInfo;
            SHGFI flags = SHGFI.SysIconIndex;// | SHGFI.UseFileAttributes;
            if (open)
                flags |= SHGFI.OpenIcon;
            if (selected)
                flags |= SHGFI.Selected;
            if (large)
                flags |= SHGFI.LargeIcon;
            else
                flags |= SHGFI.SmallIcon;
            IntPtr ret = Shell32.SHGetFileInfo(path, 0, out fileInfo, (uint)Marshal.SizeOf(typeof(SHFILEINFO)), flags);
            return fileInfo.iIcon;
        }

        public enum FileOperation : uint
        {
            Move = 0x0001,
            Copy = 0x0002,
            Delete = 0x0003,
            Rename = 0x0004,
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        public struct SHFILEOPSTRUCT
        {
            public IntPtr hwnd;
            public FileOperation wFunc;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string pFrom;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string pTo;
            public FileOperationFlags fFlags;
            //public bool fAnyOperationsAborted;
            // the bool size is 1 byte. in the platform SDK BOOL is just an int
            public Int32 fAnyOperationsAborted;
            public IntPtr hNameMappings;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string lpszProgressTitle;
        }

        [Flags]
        public enum FileOperationFlags : ushort
        {
            MultiDestFiles = 0x0001,
            ConfirmMouse = 0x0002,
            Silent = 0x0004,  // don't create progress/report
            RenameOnCollision = 0x0008,
            NoConfirmation = 0x0010,  // Don't prompt the user.
            WantMappingHandle = 0x0020,  // Fill in SHFILEOPSTRUCT.hNameMappings
            // Must be freed using SHFreeNameMappings
            AllowUndo = 0x0040,
            FilesOnly = 0x0080,  // on *.*, do only files
            SimpleProgress = 0x0100,  // means don't show names of files
            NoConfirmMakeDir = 0x0200,  // don't confirm making any needed dirs
            NoErrorUI = 0x0400,  // don't put up error UI
            NoCopySecurityAttributes = 0x0800,  // dont copy NT file Security Attributes
            NoRecursion = 0x1000,  // don't recurse into directories.
            NoConnectedElements = 0x2000,  // don't operate on connected elements.
            WantNukeWarning = 0x4000,  // during delete operation, warn if nuking instead of recycling (partially overrides FOF_NOCONFIRMATION)
            NoRecurseParse = 0x8000,  // treat reparse points as objects, not containers
        }
        [DllImport("shell32.dll", CharSet = CharSet.Unicode)]
        public static extern int SHFileOperation([In] ref SHFILEOPSTRUCT lpFileOp);



    }//class Shell32
    // from ShObjIdl.h
 
}
